package com.icas.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.icas.entity.databaseentity.AccountEntity;
import com.icas.entity.resultentity.Result;
import com.icas.enums.MsgResultEnum;
import com.icas.exception.JsonFormatException;
import com.icas.exception.LoginException;
import com.icas.exception.UpDateException;
import com.icas.service.AccountService;
import com.icas.util.Constant;
import com.icas.util.StringUtils;
import com.icas.util.jwt.JwtToken;
import com.icas.util.jwt.JwtUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * 账户处理类
 *
 * @author tocchen
 * @date 2022/6/6 16:17
 * @since jdk 1.8
 **/
@RestController
@RequestMapping("/kingzhihui/account")
public class AccountController {

    @Autowired AccountService db;

    static Logger logger = LoggerFactory.getLogger(AccountController.class);


    /**
     * 初始化账户集合密码 只允许教师和系统维护人员使用
     * @param json json对象
     * @return 处理结果
     */
    @PostMapping("/init")
    @RequiresRoles(logical = Logical.OR, value = {"0","1"})
    public Result<?> initAccount(@RequestBody JSONObject json){

        ArrayList<String> failAccount = new ArrayList<>();

        // 解析JSON 获取JSON中stuList数组内容 并转换为List集合
        JSONArray jsonArray = json.getJSONArray("stuList");
        if (jsonArray == null){
            throw new JsonFormatException();
        }

        List<String> accountList = jsonArray.toJavaList(String.class);

        for(String account : accountList){
            AccountEntity info = db.byAccountGetInfo(account);
            if (info != null){
                db.updatePwd(info.getId(), Constant.NORMAL_PASSWORD);
            }else {
                failAccount.add(account);
            }
        }

        if (accountList.size() == failAccount.size()){
            throw new UpDateException();
        }else {
            logger.info("账户更新了"+(accountList.size()-failAccount.size())+"条数据");
            return Result.oK(failAccount.size()==0?null:failAccount);
        }
    }

    /**
     * 执行登录操作
     * @param json 登录对应的实体类
     * @return 结果集
     */
    @PostMapping("/login")
    public Result<?> executeLogin(@RequestBody JSONObject json){

        String account = json.getString("account");
        String password = json.getString("password");

        if (StringUtils.isEmpty(account,password)){
            throw new LoginException();
        }

        AccountEntity info = db.login(account,password);

        if (ObjectUtils.isEmpty(info)){
            throw new LoginException(MsgResultEnum.Account_ERROR.getMsg());
        }

        try{
            String token = JwtUtils.createToken(info);
            info.setPassword(null);
            info.setSalt(null);
            info.setId(null);
            info.setCourses(null);

            Subject subject = SecurityUtils.getSubject();
            subject.login(new JwtToken(token));

            if(subject.isAuthenticated()){
                return Result.oK(info,token);
            }else {
                throw new LoginException("登录失败");
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new LoginException(MsgResultEnum.Account_ERROR.getMsg());
        }
    }

    /**
     * 校验密码的正确性后修改密码操作
     * @param token token值
     * @param json oldPassword和newPassword信息
     * @return 结果集
     */
    @PostMapping("/update_pwd")
    @RequiresAuthentication
    public Result<?> updatePwd(@RequestHeader(value = "token") String token, @RequestBody JSONObject json){
        // 通过token解析id值
        String id = JwtUtils.getId(token);
        String oldPassword = json.getString("oldPassword");
        String newPassword = json.getString("newPassword");

        if (StringUtils.isEmpty(id,oldPassword,newPassword)){
            throw new JsonFormatException();
        }

        AccountEntity accountEntity = db.byIdGetInfo(id);

        if (accountEntity == null){
            throw new UpDateException();
        }

        Md5Hash md5Hash = new Md5Hash(oldPassword, accountEntity.getSalt(), Constant.HASH_NUM);
        if (!(accountEntity.getPassword().equals(md5Hash.toHex()))){
            return Result.error(MsgResultEnum.UPPASSWORD_ERROR);
        }
        Boolean updateBoolean = db.updatePwd(id, newPassword);

        return updateBoolean?Result.ok():Result.error(MsgResultEnum.UPPASSWORD_ERROR);

    }

}
